﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using ScrumTable.Common;

#endregion

namespace ScrumTable.DL.Data.Common.Serialization
{
    /// <summary>
    /// Contains the properties and child elements of the DataValue
    /// element. This class is needed for serialization purposes.
    /// </summary>
    [XmlRoot("DataValue")]
    public class DataValue : IXmlSerializable
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        private const string NameAttribute = "Name";
        private object _elementDataToWrite;
        private string _elementDataToRead;

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------
        
        /// <summary>
        /// Specifies the Name attribute.
        /// </summary>
        [XmlIgnore]
        public string Name { get; set; }

        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        /// <summary>
        /// Public constructor needed for serialization facilities.
        /// </summary>
        public DataValue()
        {
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// This method is reserved and should not be used. When implementing the IXmlSerializable
        /// interface, you should return null (Nothing in Visual Basic) from this method, and instead,
        /// if specifying a custom schema is required, apply the <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute"/>
        /// to the class.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Xml.Schema.XmlSchema"/> that describes the XML representation
        /// of the object that is produced by the <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)"/>
        /// method and consumed by the <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)"/> method.
        /// </returns>
        XmlSchema IXmlSerializable.GetSchema()
        {
            return null;
        }

        /// <summary>
        /// Generates an object from its XML representation.
        /// </summary>
        /// <param name="reader">The <see cref="T:System.Xml.XmlReader"/> stream from which the object is deserialized.</param>
        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            string nodeName = reader.Name;
            Name = reader[NameAttribute];
            reader.Read(); // step over <DataValue>

            if (reader.HasValue)
                _elementDataToRead = reader.ReadString(); // read element content

            if (reader.NodeType == XmlNodeType.EndElement && reader.Name == nodeName)
                reader.Read(); // skip </DataValue> element if any
        }

        /// <summary>
        /// Converts an object into its XML representation.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Xml.XmlWriter"/> stream to which the object is serialized.</param>
        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            writer.WriteAttributeString(NameAttribute, Name);

            if (_elementDataToWrite != null)
                writer.WriteValue(_elementDataToWrite);
        }

        /// <summary>
        /// Returns the data stored in the current element and converts it to the given
        /// type.
        /// </summary>
        /// <param name="toConvert">Specifies the target type.</param>
        /// <returns>Returns the retrieve object.</returns>
        public object GetData(Type toConvert)
        {
            return ObjectUtil.ConvertFromString(_elementDataToRead, toConvert);
        }

        internal void SetData(object data, string recommendedPath, IDataResolver resolver)
        {
            _elementDataToWrite = ObjectUtil.ConvertToString(
                data,
                o => ((o is Uri) && ((Uri) data).IsAbsoluteUri),
                o => resolver.ResolveTo(recommendedPath, (Uri)o).ToString());
        }

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        #endregion
    }
}